package tp.badugi.net;

import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

/**
 * This class is meant for storing information about the game.
 * An instance of this class is passed once, through the
 * {@link StatusUpdateListener#successfullyJoinedTable(GameStatus) successfullyJoinedTable}
 * method when a client connects to the server.
 * <p>
 * The information stored in this class is particularly useful for when a client reconnects 
 * after getting disconnected and needs to update all its information. 
 * 
 * @author bartek
 *
 */
public class GameStatus {
	
	public GameStatus() { }
	
	public GameStatus(GameStatus gameStatus) {
		myPlayerNumber = gameStatus.myPlayerNumber;
		myChipCount = gameStatus.myChipCount;
		if (gameStatus.myCards != null) {
			myCards = gameStatus.myCards.clone();
		}
		if (gameStatus.playerStatuses != null) {
			playerStatuses = gameStatus.playerStatuses.clone();
		}
		if (gameStatus.playerNames != null) {
			playerNames = gameStatus.playerNames.clone();
		}
		if (gameStatus.playerChipCounts != null) {
			playerChipCounts = gameStatus.playerChipCounts.clone();
		}
		if (gameStatus.playerPotContributions != null) {
			playerPotContributions = gameStatus.playerPotContributions.clone();
		}
		numberOfPlayers = gameStatus.numberOfPlayers;
		playerWithDealerButton = gameStatus.playerWithDealerButton;
		smallBlind = gameStatus.smallBlind;
		bigBlind = gameStatus.bigBlind;
		bettingRound = gameStatus.bettingRound;
		playerInAction = gameStatus.playerInAction;
		betAmount = gameStatus.betAmount;
		potSize = gameStatus.potSize;
		tableName = gameStatus.tableName;
	}
	
	/**
	 * Player's number.
	 */
	public int myPlayerNumber;
	
	/**
	 * Player's current total chip count.
	 */
	public long myChipCount;
	
	/**
	 * Player's cards. This is an array of four Strings, each representing a card.
	 * <p>
	 * Each card is represented by a two-character String. The first
	 * character signifies the rank (2, 3, 4, 5, 6, 7, 8, 9, T, J, Q, K, A).
	 * And the second character signifies the suit (S, H, D, C).
	 * For example "QS" means a queen of spades.
	 */
	public String[] myCards;
	
	/**
	 * The number of players joined to the server
	 */
	public int numberOfPlayers;
	
	/**
	 * The status of each player. True if connected. False if disconnected.
	 */
	public boolean[] playerStatuses;
	
	/**
	 * The name of each player or null if that player left the game (!= disconnected).
	 */
	public String[] playerNames;
	
	/**
	 * The chip count of each player.
	 */
	public long[] playerChipCounts;
	
	/**
	 * The amount of chips each player contributed to the pot.
	 */
	public long[] playerPotContributions;
	
	/**
	 * The player number of the player with the dealer button.
	 */
	public int playerWithDealerButton;
	
	/**
	 * The small blind amount.
	 */
	public long smallBlind;
	
	/**
	 * The big blind amount.
	 */
	public long bigBlind;
	
	/**
	 * The number of the betting round.
	 */
	public int bettingRound;
	
	/**
	 * The number of the player in action or -1 if the game hasn't started.
	 */
	public int playerInAction;
	
	/**
	 * The total amount of chips contributed to the pot by the player who last bet or raised.
	 */
	public long betAmount;
	
	/**
	 * The current amount of chips in the pot.
	 */
	public long potSize;
	
	/**
	 * The table name.
	 */
	public String tableName;
	
	public JSONObject toJSONObject() {
		try {
			JSONObject jsonObject = new JSONObject();
			jsonObject.put("myPlayerNumber", myPlayerNumber);
			jsonObject.put("myChipCount", myChipCount);
			jsonObject.put("myCards", myCards);
			jsonObject.put("numberOfPlayers", numberOfPlayers);
			jsonObject.put("playerStatuses", playerStatuses);
			jsonObject.put("playerNames", playerNames);
			jsonObject.put("playerChipCounts", playerChipCounts);
			jsonObject.put("playerPotContributions", playerPotContributions);
			jsonObject.put("playerWithDealerButton", playerWithDealerButton);
			jsonObject.put("smallBlind", smallBlind);
			jsonObject.put("bigBlind", bigBlind);
			jsonObject.put("bettingRound", bettingRound);
			jsonObject.put("playerInAction", playerInAction);
			jsonObject.put("betAmount", betAmount);
			jsonObject.put("potSize", potSize);
			jsonObject.put("tableName", tableName);
			return jsonObject;
		}
		// Try to recover from formatting error.
		catch (JSONException e) {
			System.err.println("Error creating JSON encoded String");
			e.printStackTrace();
			return null;
		}
	}
	
	public static GameStatus fromJSONObject(JSONObject jsonObject) {
		try {
			GameStatus gameStatus = new GameStatus();
			
			gameStatus.myPlayerNumber = jsonObject.getInt("myPlayerNumber");
			
			gameStatus.myChipCount = jsonObject.getLong("myChipCount");
			
			if (!jsonObject.isNull("myCards")) {
				JSONArray myCards = jsonObject.getJSONArray("myCards");
				gameStatus.myCards = new String[myCards.length()];
				for (int i = 0; i < myCards.length(); i++) {
					gameStatus.myCards[i] = myCards.getString(i);
				}
			}
			
			gameStatus.numberOfPlayers = jsonObject.getInt("numberOfPlayers");
			
			JSONArray playerStatuses = jsonObject.getJSONArray("playerStatuses");
			gameStatus.playerStatuses = new boolean[playerStatuses.length()];
			for (int i = 0; i < playerStatuses.length(); i++) {
				gameStatus.playerStatuses[i] = playerStatuses.getBoolean(i);
			}
			
			JSONArray playerNames = jsonObject.getJSONArray("playerNames");
			gameStatus.playerNames = new String[playerNames.length()];
			for (int i = 0; i < playerNames.length(); i++) {
				gameStatus.playerNames[i] = playerNames.getString(i);
			}
			
			JSONArray playerChipCounts = jsonObject.getJSONArray("playerChipCounts");
			gameStatus.playerChipCounts = new long[playerChipCounts.length()];
			for (int i = 0; i < playerChipCounts.length(); i++) {
				gameStatus.playerChipCounts[i] = playerChipCounts.getLong(i);
			}
			
			JSONArray playerPotContributions = jsonObject.getJSONArray("playerPotContributions");
			gameStatus.playerPotContributions = new long[playerPotContributions.length()];
			for (int i = 0; i < playerPotContributions.length(); i++) {
				gameStatus.playerPotContributions[i] = playerPotContributions.getLong(i);
			}
			
			gameStatus.playerWithDealerButton = jsonObject.getInt("playerWithDealerButton");
			
			gameStatus.smallBlind = jsonObject.getLong("smallBlind");
			
			gameStatus.bigBlind = jsonObject.getLong("bigBlind");
			
			gameStatus.bettingRound = jsonObject.getInt("bettingRound");
			
			gameStatus.playerInAction = jsonObject.getInt("playerInAction");
			
			gameStatus.betAmount = jsonObject.getLong("betAmount");
			
			gameStatus.potSize = jsonObject.getLong("potSize");
			
			gameStatus.tableName = jsonObject.getString("tableName");
			
			return gameStatus;
		}
		// Try to recover from formatting error.
		catch (JSONException e) {
			System.err.println("Error creating JSON encoded String");
			e.printStackTrace();
			return null;
		}
	}
}
